bitkeeper revision 1.1389.3.1 (42714dabVSywx2XWGjgw2J54ZylwYg)
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Thu, 28 Apr 2005 20:55:07 +0000 (20:55 +0000)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Thu, 28 Apr 2005 20:55:07 +0000 (20:55 +0000)
Ensure block/yield hypercalls always return a sane return code.

Ensure callers of __enter_scheduler take appropriate arch-specific
action if no context switch occurs (callers from arch/x86 do not
expect to return from a call into the scheduler).

This fixes wildly unintuitive behaviour of do_block() for the
VMX team.

Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/ia64/xenmisc.c
xen/arch/x86/domain.c
xen/arch/x86/x86_32/entry.S
xen/arch/x86/x86_64/entry.S
xen/common/schedule.c
xen/include/xen/sched.h

index d740fe7aa9b1fdabecb1d9d32111b6d81635149f..b46e4f8f11c385ab62ed6f8095342027b07dbc4f 100644 (file)
@@ -278,6 +278,11 @@ if (!i--) { printk("+",id); cnt[id] = 100; }
        if (vcpu_timer_expired(current)) vcpu_pend_timer(current);
 }
 
+void continue_running(struct exec_domain *same)
+{
+    /* nothing to do */
+}
+
 void panic_domain(struct pt_regs *regs, const char *fmt, ...)
 {
        va_list args;
index 322b200a3a735a7d0556238528631ef72a22d97a..0cb953c1bb6c09ff123da9d08f170734da55289a 100644 (file)
@@ -794,7 +794,12 @@ void context_switch(struct exec_domain *prev, struct exec_domain *next)
     clear_bit(EDF_RUNNING, &prev->ed_flags);
 
     schedule_tail(next);
+    BUG();
+}
 
+void continue_running(struct exec_domain *same)
+{
+    schedule_tail(same);
     BUG();
 }
 
index 60f154b270e64508303e4da5f6d2aef3789b8391..8a36e7ba027474b041781ce9fdd837823c8f24af 100644 (file)
@@ -652,6 +652,12 @@ ENTRY(setup_vm86_frame)
         addl $16,%esp
         ret
 
+do_arch_sched_op:
+        # Ensure we return success even if we return via schedule_tail()
+        xorl %eax,%eax
+        movl %eax,UREGS_eax+4(%esp)
+        jmp  SYMBOL_NAME(do_sched_op)
+
 do_switch_vm86:
         # Discard the return address
         addl $4,%esp
@@ -718,7 +724,7 @@ ENTRY(hypercall_table)
         .long SYMBOL_NAME(do_stack_switch)
         .long SYMBOL_NAME(do_set_callbacks)
         .long SYMBOL_NAME(do_fpu_taskswitch)     /*  5 */
-        .long SYMBOL_NAME(do_sched_op)
+        .long SYMBOL_NAME(do_arch_sched_op)
         .long SYMBOL_NAME(do_dom0_op)
         .long SYMBOL_NAME(do_set_debugreg)
         .long SYMBOL_NAME(do_get_debugreg)
index b4280a1ff56e399aa96ca618b08759977d869c31..092828ac236d14cab2af5194299a8d381943480f 100644 (file)
@@ -523,6 +523,12 @@ ENTRY(nmi)
         call  SYMBOL_NAME(do_nmi)
        jmp   restore_all_xen
 
+do_arch_sched_op:
+        # Ensure we return success even if we return via schedule_tail()
+        xorl  %eax,%eax
+        movq  %rax,UREGS_rax+8(%rsp)
+        jmp   SYMBOL_NAME(do_sched_op)
+
 .data
 
 ENTRY(exception_table)
@@ -554,7 +560,7 @@ ENTRY(hypercall_table)
         .quad SYMBOL_NAME(do_stack_switch)
         .quad SYMBOL_NAME(do_set_callbacks)
         .quad SYMBOL_NAME(do_fpu_taskswitch)     /*  5 */
-        .quad SYMBOL_NAME(do_sched_op)
+        .quad SYMBOL_NAME(do_arch_sched_op)
         .quad SYMBOL_NAME(do_dom0_op)
         .quad SYMBOL_NAME(do_set_debugreg)
         .quad SYMBOL_NAME(do_get_debugreg)
index 8062fdac73fcae32608a0db662f65baea2762df6..4123231dd1b788a8d4d289191b7075b333265ba7 100644 (file)
@@ -228,7 +228,9 @@ long do_block(void)
 
     /* Check for events /after/ blocking: avoids wakeup waiting race. */
     if ( event_pending(ed) )
+    {
         clear_bit(EDF_BLOCKED, &ed->ed_flags);
+    }
     else
     {
         TRACE_2D(TRC_SCHED_BLOCK, ed->domain->id, ed->eid);
@@ -382,7 +384,7 @@ static void __enter_scheduler(void)
     spin_unlock_irq(&schedule_data[cpu].schedule_lock);
 
     if ( unlikely(prev == next) )
-        return;
+        return continue_running(prev);
     
     perfc_incrc(sched_ctx);
 
index 915abaeddfe98af049f01c526d260808399cfbe3..37ab3ff744cad1c52b87be428c745286e74f3831 100644 (file)
@@ -210,7 +210,7 @@ static inline void get_knownalive_domain(struct domain *d)
     atomic_inc(&d->refcnt);
     ASSERT(!(atomic_read(&d->refcnt) & DOMAIN_DESTRUCTED));
 }
-  
+
 extern struct domain *do_createdomain(
     domid_t dom_id, unsigned int cpu);
 extern int construct_dom0(
@@ -265,10 +265,15 @@ extern void sync_lazy_execstate_cpuset(unsigned long cpuset);
 extern void sync_lazy_execstate_all(void);
 extern int __sync_lazy_execstate(void);
 
+/* Called by the scheduler to switch to another exec_domain. */
 extern void context_switch(
     struct exec_domain *prev, 
     struct exec_domain *next);
 
+/* Called by the scheduler to continue running the current exec_domain. */
+extern void continue_running(
+    struct exec_domain *same);
+
 void domain_init(void);
 
 int idle_cpu(int cpu); /* Is CPU 'cpu' idle right now? */